<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<title>when_any, heterogeneous types</title>
<link rel="stylesheet" href="../../../../../../../doc/src/boostbook.css" type="text/css">
<meta name="generator" content="DocBook XSL Stylesheets V1.75.2">
<link rel="home" href="../../../index.html" title="Chapter&#160;1.&#160;Fiber">
<link rel="up" href="../when_any.html" title="when_any">
<link rel="prev" href="when_any__produce_first_success.html" title="when_any, produce first success">
<link rel="next" href="when_any__a_dubious_alternative.html" title="when_any, a dubious alternative">
</head>
<body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
<table cellpadding="2" width="100%"><tr>
<td valign="top"><img alt="Boost C++ Libraries" width="277" height="86" src="../../../../../../../boost.png"></td>
<td align="center"><a href="../../../../../../../index.html">Home</a></td>
<td align="center"><a href="../../../../../../../libs/libraries.htm">Libraries</a></td>
<td align="center"><a href="http://www.boost.org/users/people.html">People</a></td>
<td align="center"><a href="http://www.boost.org/users/faq.html">FAQ</a></td>
<td align="center"><a href="../../../../../../../more/index.htm">More</a></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="when_any__produce_first_success.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../when_any.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="when_any__a_dubious_alternative.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
<div class="section">
<div class="titlepage"><div><div><h4 class="title">
<a name="fiber.when_any.when_any.when_any__heterogeneous_types"></a><a class="link" href="when_any__heterogeneous_types.html" title="when_any, heterogeneous types">when_any,
        heterogeneous types</a>
</h4></div></div></div>
<p>
          We would be remiss to ignore the case in which the various task functions
          have distinct return types. That means that the value returned by the first
          of them might have any one of those types. We can express that with <a href="http://www.boost.org/doc/libs/release/doc/html/variant.html" target="_top">Boost.Variant</a>.
        </p>
<p>
          To keep the example simple, we'll revert to pretending that none of them
          can throw an exception. That makes <code class="computeroutput"><span class="identifier">wait_first_value_het</span><span class="special">()</span></code> strongly resemble <a class="link" href="when_any__return_value.html#wait_first_value"><code class="computeroutput"><span class="identifier">wait_first_value</span><span class="special">()</span></code></a>.
          We can actually reuse <a class="link" href="when_any__return_value.html#wait_first_value_impl"><code class="computeroutput"><span class="identifier">wait_first_value_impl</span><span class="special">()</span></code></a>,
          merely passing <code class="computeroutput"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span><span class="special">&lt;</span><span class="identifier">T0</span><span class="special">,</span> <span class="identifier">T1</span><span class="special">,</span> <span class="special">...&gt;</span></code> as the queue's value type rather
          than the common <code class="computeroutput"><span class="identifier">T</span></code>!
        </p>
<p>
          Naturally this could be extended to use <a class="link" href="when_any__produce_first_success.html#wait_first_success"><code class="computeroutput"><span class="identifier">wait_first_success</span><span class="special">()</span></code></a>
          semantics instead.
        </p>
<p>
</p>
<pre class="programlisting"><span class="comment">// No need to break out the first Fn for interface function: let the compiler</span>
<span class="comment">// complain if empty.</span>
<span class="comment">// Our functions have different return types, and we might have to return any</span>
<span class="comment">// of them. Use a variant, expanding std::result_of&lt;Fn()&gt;::type for each Fn in</span>
<span class="comment">// parameter pack.</span>
<span class="keyword">template</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="special">...</span> <span class="identifier">Fns</span> <span class="special">&gt;</span>
<span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special">&lt;</span> <span class="identifier">Fns</span><span class="special">()</span> <span class="special">&gt;::</span><span class="identifier">type</span> <span class="special">...</span> <span class="special">&gt;</span>
<span class="identifier">wait_first_value_het</span><span class="special">(</span> <span class="identifier">Fns</span> <span class="special">&amp;&amp;</span> <span class="special">...</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">{</span>
    <span class="comment">// Use buffered_channel&lt;boost::variant&lt;T1, T2, ...&gt;&gt;; see remarks above.</span>
    <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span><span class="special">&lt;</span> <span class="keyword">typename</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">result_of</span><span class="special">&lt;</span> <span class="identifier">Fns</span><span class="special">()</span> <span class="special">&gt;::</span><span class="identifier">type</span> <span class="special">...</span> <span class="special">&gt;</span> <span class="identifier">return_t</span><span class="special">;</span>
    <span class="keyword">typedef</span> <span class="identifier">boost</span><span class="special">::</span><span class="identifier">fibers</span><span class="special">::</span><span class="identifier">buffered_channel</span><span class="special">&lt;</span> <span class="identifier">return_t</span> <span class="special">&gt;</span> <span class="identifier">channel_t</span><span class="special">;</span>
    <span class="keyword">auto</span> <span class="identifier">chanp</span><span class="special">(</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">make_shared</span><span class="special">&lt;</span> <span class="identifier">channel_t</span> <span class="special">&gt;(</span> <span class="number">64</span><span class="special">)</span> <span class="special">);</span>
    <span class="comment">// launch all the relevant fibers</span>
    <span class="identifier">wait_first_value_impl</span><span class="special">&lt;</span> <span class="identifier">return_t</span> <span class="special">&gt;(</span> <span class="identifier">chanp</span><span class="special">,</span>
                                       <span class="identifier">std</span><span class="special">::</span><span class="identifier">forward</span><span class="special">&lt;</span> <span class="identifier">Fns</span> <span class="special">&gt;(</span> <span class="identifier">functions</span><span class="special">)</span> <span class="special">...</span> <span class="special">);</span>
    <span class="comment">// retrieve the first value</span>
    <span class="identifier">return_t</span> <span class="identifier">value</span><span class="special">(</span> <span class="identifier">chanp</span><span class="special">-&gt;</span><span class="identifier">value_pop</span><span class="special">()</span> <span class="special">);</span>
    <span class="comment">// close the channel: no subsequent push() has to succeed</span>
    <span class="identifier">chanp</span><span class="special">-&gt;</span><span class="identifier">close</span><span class="special">();</span>
    <span class="keyword">return</span> <span class="identifier">value</span><span class="special">;</span>
<span class="special">}</span>
</pre>
<p>
        </p>
<p>
          It might be called like this:
        </p>
<p>
</p>
<pre class="programlisting"><span class="identifier">boost</span><span class="special">::</span><span class="identifier">variant</span><span class="special">&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">string</span><span class="special">,</span> <span class="keyword">double</span><span class="special">,</span> <span class="keyword">int</span> <span class="special">&gt;</span> <span class="identifier">result</span> <span class="special">=</span>
    <span class="identifier">wait_first_value_het</span><span class="special">(</span>
            <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="string">"wfvh_third"</span><span class="special">,</span>  <span class="number">150</span><span class="special">);</span> <span class="special">},</span>
            <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="number">3.14</span><span class="special">,</span>          <span class="number">100</span><span class="special">);</span> <span class="special">},</span>
            <span class="special">[](){</span> <span class="keyword">return</span> <span class="identifier">sleeper</span><span class="special">(</span><span class="number">17</span><span class="special">,</span>             <span class="number">50</span><span class="special">);</span> <span class="special">});</span>
<span class="identifier">std</span><span class="special">::</span><span class="identifier">cout</span> <span class="special">&lt;&lt;</span> <span class="string">"wait_first_value_het() =&gt; "</span> <span class="special">&lt;&lt;</span> <span class="identifier">result</span> <span class="special">&lt;&lt;</span> <span class="identifier">std</span><span class="special">::</span><span class="identifier">endl</span><span class="special">;</span>
<span class="identifier">assert</span><span class="special">(</span><span class="identifier">boost</span><span class="special">::</span><span class="identifier">get</span><span class="special">&lt;</span> <span class="keyword">int</span> <span class="special">&gt;(</span> <span class="identifier">result</span><span class="special">)</span> <span class="special">==</span> <span class="number">17</span><span class="special">);</span>
</pre>
<p>
        </p>
</div>
<table xmlns:rev="http://www.cs.rpi.edu/~gregod/boost/tools/doc/revision" width="100%"><tr>
<td align="left"></td>
<td align="right"><div class="copyright-footer">Copyright &#169; 2013 Oliver Kowalke<p>
        Distributed under the Boost Software License, Version 1.0. (See accompanying
        file LICENSE_1_0.txt or copy at <a href="http://www.boost.org/LICENSE_1_0.txt" target="_top">http://www.boost.org/LICENSE_1_0.txt</a>)
      </p>
</div></td>
</tr></table>
<hr>
<div class="spirit-nav">
<a accesskey="p" href="when_any__produce_first_success.html"><img src="../../../../../../../doc/src/images/prev.png" alt="Prev"></a><a accesskey="u" href="../when_any.html"><img src="../../../../../../../doc/src/images/up.png" alt="Up"></a><a accesskey="h" href="../../../index.html"><img src="../../../../../../../doc/src/images/home.png" alt="Home"></a><a accesskey="n" href="when_any__a_dubious_alternative.html"><img src="../../../../../../../doc/src/images/next.png" alt="Next"></a>
</div>
</body>
</html>
